import * as actionTypes from "./constants";

import { getRandomNumber } from "@/utils/math-utils";
import { parseLyric } from "@/utils/parse-lyric";

import { 
  getSongDetail, 
  getLyric,
  getSongsList,
  getRelevantList 
} from "@/services/player";

//改变当前播放歌曲
const changeSongDetailAction = (currentSong) => ({
  type: actionTypes.CHANGE_SONG_DETAIL,
  currentSong
});

//改变播放列表
const changePlayListAction = (playList) => ({
  type: actionTypes.CHNAGE_PLAY_LIST,
  playList
});

//改变播放歌曲的索引
const changeCurrentSongIndexAcyion = (index) => ({
  type: actionTypes.CHNAGE_CURRENT_SONG_INDEX,
  index
})

//改变歌曲歌词
const changeLyricListAction = (lyricList) => ({
  type: actionTypes.CHANGE_LYRIC_LIST,
  lyricList
});

//改变播放顺序
export const changeSequenceAction = (sequence) => ({
  type: actionTypes.CHANGE_SEQUENCE,
  sequence
});

//改变当前播放歌词索引
export const changeLyricIndexAction = (index) => ({
  type: actionTypes.CHANGE_LYRIC_INDEX,
  index
});

const changeSongsListAction = (songsList) => ({
  type: actionTypes.CHANGE_SONGS_LIST,
  songsList
});

const changeRelevantListAction = (relevants) => ({
  type: actionTypes.CHANGE_RELEVANT_LIST,
  relevants
}); 

//歌曲详情
export const getSongDetailAction = (ids) => {
  return (dispatch, getState) => {
    
    const playList = getState().getIn(["player", "playList"]);
    //1. 是否存在播放列表
    const songIndex = playList.findIndex(item => item.id === ids);
    /**
     *  两种情况
     * 一、存在: 根据索引取出歌曲，纪录index。
     * 二、不存在：拿着ids请求，然后添加，纪录index。
     */
    if (songIndex !== -1) {
      const song = playList[songIndex];
      dispatch(changeSongDetailAction(song));
      dispatch(changeCurrentSongIndexAcyion(songIndex));

      //获取歌词
      dispatch(getLyricAction(song.id))
    } else {
      getSongDetail(ids).then(res => {
        const song = res.songs && res.songs[0];
        if (!song) return; //不存在return
        const newPlayList = [...playList];
        newPlayList.push(song);
        const indey = newPlayList.length - 1;
        dispatch(changeSongDetailAction(song))
        dispatch(changePlayListAction(newPlayList))
        dispatch(changeCurrentSongIndexAcyion(indey));

        //获取歌词
        dispatch(getLyricAction(song.id))
      })
    }

  }
};

//根据播放顺序&下一首/上一首 改变播放歌曲
export const changeCurrentIndexAndSongAction = (tag) => {
  return (dispatch, getState) => {
    const playList = getState().getIn(["player", "playList"]);
    const sequence = getState().getIn(["player", "sequence"]);
    let songIndex = getState().getIn(["player", "currentSongIndex"]);
    
    switch (sequence) {   //0/顺序 1/随机 2/单曲   顺序和单曲的逻辑一样，所以只判断随机。
      case 1:
        //创造一个0~1的随机数 * arr.length。
        //使用while语句满足条件，就会一直执行循环体里的语句，直到不满足条件，再执行后面的代码。
        //这里的实现就是如果随机到当前歌曲(songIndex)，就再次执行随机，知道不相等。
        let randomIndex = getRandomNumber(playList.length);
        while (randomIndex === songIndex) {
          randomIndex = getRandomNumber(playList.length);
        }
        songIndex = randomIndex;
        break;
      default:
        songIndex += tag;
        //tag = 1下一首，最后一首时再点击播放第一首；
        if (songIndex >= playList.length) songIndex = 0; 
        //tag = -1上一首, 在第一首再点击上一首时播放最后一首；
        if (songIndex < 0) songIndex = playList.length - 1;
    }

    const song = playList[songIndex];
    dispatch(changeSongDetailAction(song));
    dispatch(changeCurrentSongIndexAcyion(songIndex));

    //获取歌词
    dispatch(getLyricAction(song.id))
  }
};

//获取歌词
export const getLyricAction = (id) => {
  return dispatch => {
    getLyric(id).then(res => {
      const lyric = res.lrc.lyric;
      const lyricList = parseLyric(lyric);
      dispatch(changeLyricListAction(lyricList));
    })
  }
};

//包含歌单
export const getSongsListAction = () => {
  return (dispatch, getState) => {
    const id = getState().getIn(["player", "currentSong"]).id;
    if (!id) return;

    getSongsList(id).then(res => {
      dispatch(changeSongsListAction(res.playlists));
    })
  }
};

//相似歌曲
export const getRelevantListAction = () => {
  return (dispatch, getState) => {
    const id = getState().getIn(["player", "currentSong"]).id;
    if (!id) return;
    
    getRelevantList(id).then(res => {
      dispatch(changeRelevantListAction(res.songs));
    })
  }
};